/* Document.h
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

Header file for the Hexie Document class, whcih represents a binary data file that has been
loaded and the markup that the user has created for that file.
*/

#ifndef __HEXIE_DOCUMENT_H__
#define __HEXIE_DOCUMENT_H__

#include <string>

#include "Type.h"

#include <map>
#include <set>
#include <ostream>
#include <istream>

using std::string;
using std::map;
using std::set;
using std::ostream;
using std::istream;



class Document : protected string {
public:
	// Default constructor. Creates an empty document.
	Document();
	
	// Load the given file. If the file name is in the format "file.ext.hexie",
	// the actual data is loaded from "file.ext" instead. If a "file.ext.hexie"
	// exists, markup is read from it.
	void Load(const string &path);
	// Save the markup for the current file as "current/file/path.ext.hexie".
	void Save() const;
	// Get the name of the file.
	const string &FileName() const;
	
	// Editing the data is not allowed, so only constant iterators are given.
	typedef string::const_iterator It;
	// Get an iterator to the start of the document.
	It Begin() const;
	// Get an iterator to the end of the document.
	It End() const;
	// Get the size of the document, in bytes.
	size_t Size() const;
	
	// Get the cursor position.
	It Cursor() const;
	// Get an iterator to the beginning of the selection. This may be either
	// the anchor or the cursor, depending on which comes first.
	It SelectionBegin() const;
	// Get the end of the selection, inclusive.
	// If only the cursor is selected, selection begin = end = cursor.
	It SelectionEnd() const;
	
	// Move the cursor. If keepAnchor, the selection expands to include the
	// cursor position. Otherwise, the selection becomes the cursor position.
	void SetCursor(It position, bool keepAnchor);
	// Move the cursor to the end of the current markup, if any.
	// As with SetCursor, this optionally preserves the anchor point.
	void NextCursor(bool keepAnchor);
	
	// Handle a key press by the user. In general, letters map to data types,
	// numbers to element sizes, '\b' to delete, and '\n' to line break.
	// Returns true if the key is recognized and handled.
	// If isGlobal, this key affects the default style, not the currently
	// selected data.
	bool Handle(char key, bool isGlobal);
	
	// Get the default type.
	const Type &DefaultType() const;
	// Get the map of markup.
	const map<It, Type> &Markup() const;
	// Get the set of line breaks.
	const set<It> &Breaks() const;
	
	// Get the markup (if any) of the given position.
	// If there is no user-defined markup, markup.end() is returned.
	map<It, Type>::const_iterator MarkupOf(It position) const;
	// Get a non-const iterator to the markup (if any) of the given position.
	map<It, Type>::iterator MarkupOf(It position);
	
	
private:
	// Read the data from the given path. Return false if unable to read it.
	bool ReadFile(const string &path);
	// Read the markup from markupPath. If the file does not exist, start
	// out with no markup entered.
	void ReadMarkup();
	
	// Delete all markup contained in the current selection.
	void DeleteMarkup();
	// Delete all breaks in the current selection.
	void DeleteBreaks();
	
	// Write a number to the given output stream, using multiple bytes if necessary.
	static void WriteValue(size_t value, ostream &out);
	// Read a number that was written using the Write() function above.
	static size_t ReadValue(istream &in);
	
	
private:
	// This type is used for displaying all data with no special markup.
	Type defaultType;
	
	// This map stores the markup that the user has created.
	// It is maintained in such a way that no two marks overlap: if a new
	// mark overlaps an old one, the old one is deleted.
	map<It, Type> markup;
	// This set stores the line breaks inserted by the user.
	set<It> breaks;
	
	// The selection is defined by a cursor and an anchor point. Everything
	// between these two, inclusive, is "selected."
	It cursor;
	It anchor;
	
	// This is the path to the markup file (which may not be saved yet).
	string markupFilePath;
	// This is the name of the file.
	string fileName;
};



#endif

/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */
